
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>

#include "ffmpeg/avcodec.h"
#include "encode.h"
#include "global.h"

#define OUTBUF_SIZE width*height*10




struct mpeg_encode* hunter_encode_alloc(char* file_name, char* index_file) 
{
	struct mpeg_encode* me;

	me = (struct mpeg_encode*) malloc(sizeof(struct mpeg_encode));
	if (!me) {
		fprintf( stderr, "Failed to hutern encode alloc\n" );
		return NULL;
	}

	me->f = me->f_index = NULL;

	me->f = fopen(file_name, "a+");
	if(me->f == NULL) {
		fprintf( stderr, "Faile to file open\n");
		return NULL;
	}
	fseek(me->f, 0, SEEK_END);
	

	me->codec_context = avcodec_alloc_context();
	me->picture = avcodec_alloc_frame();
	me->outbuf= (uint8_t*) malloc( OUTBUF_SIZE );
	strcpy(me->index_file, index_file);

	return me;
}
int hunter_encode_init(struct mpeg_encode* p_mpeg)
{
	AVCodec *codec = NULL;
	AVCodecContext *c = NULL;
	AVFrame *picture = NULL;
	int pos, shift;


	p_mpeg->frame_count = 0;


	if ((p_mpeg->f_index = fopen(p_mpeg->index_file, "r+b")) == NULL) {
		fprintf(stderr, "Error : open the index file\n");
		return -1;
	}

	/* find the mpeg1 video encoder */
	codec = avcodec_find_encoder( CODEC_ID_MPEG1VIDEO );
	if ( !codec ) {
		fprintf( stderr, "codec not found\n" );
		return -1;
	}

	c = p_mpeg->codec_context;
	picture = p_mpeg->picture;

	c->pix_fmt = PIX_FMT_YUV420P;
	c->bit_rate = 400000;
	c->width = width;
	c->height = height;
	c->time_base.den = 30;  
	c->time_base.num= 1;
	c->gop_size = 10;

	c->max_b_frames=1;
	c->mb_decision = 2;

	if ( avcodec_open( c, codec ) < 0 ) {
		fprintf( stderr, "could not open codec\n" );
		return -1;
	}
	

	picture->linesize[0] = c->width;
	picture->linesize[1] = c->width / 2;
	picture->linesize[2] = c->width / 2;


}
void hunter_encode_put(struct mpeg_encode* p_mpeg, unsigned char* buf)
{

	unsigned char *y, *u, *v;
	int i, out_size;
	unsigned char temp;
	unsigned char read_temp;
	int i_pos, shift;
	int j;

	y = ( unsigned char * )buf;
	u = y + width * height;
	v = u + width * height / 4;

	p_mpeg->picture->data[0] = y;
	p_mpeg->picture->data[1] = u;
	p_mpeg->picture->data[2] = v;

	for( i = 0; i < 30 / ENCODE_FPS; i++ ) {

		out_size = avcodec_encode_video( p_mpeg->codec_context, p_mpeg->outbuf, OUTBUF_SIZE, p_mpeg->picture );
	
		if (p_mpeg->frame_count%30==0) {
			fseek(p_mpeg->f_index, p_mpeg->pos/8, SEEK_SET);
			fread(&read_temp, sizeof(unsigned char), 1, p_mpeg->f_index);	
			fseek(p_mpeg->f_index, p_mpeg->pos/8, SEEK_SET);
			shift = p_mpeg->pos % 8;
			temp = 0x80 >> shift;
			temp = temp | read_temp;
			
			fwrite(&temp, sizeof(unsigned char), 1, p_mpeg->f_index);
			
			i_pos = ftell(p_mpeg->f);
			fseek(p_mpeg->f_index, 10800+p_mpeg->pos*sizeof(int), SEEK_SET);
			fwrite(&i_pos, sizeof(int), 1, p_mpeg->f_index);

			p_mpeg->frame_count = 0;

			p_mpeg->pos++;
		}

		p_mpeg->frame_count++;

		fwrite(p_mpeg->outbuf, 1, out_size, p_mpeg->f);
	}
}


void hunter_encode_close(struct mpeg_encode* p_mpeg)
{

	if (p_mpeg) {
		if (p_mpeg->f_index)
			fclose( p_mpeg->f_index );
		if (p_mpeg->f)
			fclose( p_mpeg->f );
		if (p_mpeg->outbuf)
	  		free( p_mpeg->outbuf );
		if (p_mpeg->codec_context) {
	 		avcodec_close( p_mpeg->codec_context );
	  		free( p_mpeg->codec_context );
		}
		if (p_mpeg->picture)
		  	free( p_mpeg->picture );
		free( p_mpeg );
	}
}



